import math
import pandas as pd


def Buying(dic, closePrice, tradePersent=1, fees_Persent=0.002, Hands=100):
    """
    dic = statsdic
    closePrice = 默认0，交易后每次重新付值
    tradePresent = 默认全部交易，0-1
    fees_Present = 0.002 交易费率
    """
    AvableCash = dic["AvableCash"]
    AvableHands = int(
        AvableCash / (closePrice * Hands * (1 + fees_Persent))
    )  # 计算可以购买的手数

    if (AvableHands - 1) >= 0:

        dic["inPrice"] = closePrice
        HoldedHands = dic["HoldedHands"]
        BuyingShare = math.ceil(AvableHands * tradePersent)

        traded_Cash = BuyingShare * Hands * closePrice  # 计算成交需要花费多少钱

        dic["HoldedHands"] = HoldedHands + BuyingShare

        dic["AvableCash"] = AvableCash - traded_Cash * (1 + fees_Persent)  # 计算现金节约
        dic["ShareCost"] = closePrice * (1 + fees_Persent)
        # print('buy')
        try:
            assert dic["AvableCash"] >= 0
            assert dic["HoldedHands"] >= 0
        except Exception as e:
            print(e)
            BuyingShare = math.ceil((AvableHands - 1) * tradePersent)
            traded_Cash = BuyingShare * Hands * closePrice  # 计算成交需要花费多少钱

            dic["HoldedHands"] = HoldedHands + BuyingShare

            dic["AvableCash"] = AvableCash - traded_Cash * (1 + fees_Persent)  # 计算现金节约

        return dic, "BUY"
    else:
        return dic, "pass"


def Selling(dic, closePrice=0, tradePersent=1, fees_Persent=0.002, Hands=100):
    """
    dic = statsdic
    closePrice = 默认0，交易后每次重新付值
    tradePresent = 默认全部交易，0-1
    fees_Present = 0.002 交易费率
    """
    if dic["Share"] > 0:

        Avable_Share = dic["Share"]
        trade_Share = int(Avable_Share * tradePersent)
        Avable_Cash = dic["AvableCash"]
        if trade_Share > 0:
            dic["outPrice"] = closePrice

            Share = Avable_Share - trade_Share

            dic["Share"] = Share

            traded_Cash = closePrice * trade_Share
            fees = traded_Cash * fees_Persent

            dic["AvableCash"] = Avable_Cash + traded_Cash - fees

            dic["HoldedHands"] = Share / Hands

            dic["ShareCost"] = closePrice * (1 - fees_Persent)
            if dic["Share"] < 5:
                dic["inPrice"] = 0
            # print('sell')
            assert dic["Share"] >= 0
            return dic, "SELL"
        else:
            return dic, "pass"
    else:
        return dic, "pass"


def tradingModel(
    df_d, df_day, dic, mode="buy/sell", Hands=100, tradePersent=1, fees_Persent=0.002
):
    """
    买卖规则
    df = pd.DataFrame
    d = 天数
    dic = statsdic
    mode = 'buy'/'sell'
    Hands=100,
    tradePersent=1,
    fees_Persent=0.002
    """
    # for day in range(rang):
    # d = day + 1
    # df_d = df_d
    # df_day =df_day
    # df_day_1 = df.iloc[day - 1]

    PreClosePrice = df_day["close"]
    OpenPrice = df_d["open"]
    ClosePrice = df_d["close"]
    PreShareCost = dic["new_SharePrise"]
    PreShare = dic["Share"]
    dic["PreShare"] = PreShare
    trade = None
    if df_d["high"] >= PreClosePrice >= df_d["low"]:
        PreClosePrice = df_day["close"]
    else:
        PreClosePrice = df_d["open"]

    if mode.upper() == "BUY":
        dic, trade = Buying(
            dic,
            closePrice=PreClosePrice,
            tradePersent=tradePersent,
            fees_Persent=fees_Persent,
            Hands=Hands,
        )

    elif mode.upper() == "SELL":
        dic, trade = Selling(
            dic,
            closePrice=PreClosePrice,
            tradePersent=tradePersent,
            fees_Persent=fees_Persent,
            Hands=Hands,
        )

    dic["Share"] = dic["HoldedHands"] * Hands

    dic["TotalShareValues"] = dic["Share"] * ClosePrice  # 实际持有资金

    if dic["Share"] > 0:
        dic["PreShare"] = dic["TotalShareValues"] / dic["Share"]
    else:
        dic["PreShare"] = 0

    if trade == "BUY" or "SELL":
        new_total_Share = dic["Share"]
        new_Total_Share_cost = dic["ShareCost"] * (new_total_Share - PreShare)
        pre_Total_Share_cost = PreShareCost * PreShare

        new_pic_Shire = (
            ((pre_Total_Share_cost + new_Total_Share_cost) / new_total_Share)
            if dic["Share"] != 0
            else 0
        )

        dic["new_SharePrise"] = new_pic_Shire
        # dic['new_Total_Share_cost'] = new_Total_Share_cost
        # dic['pre_Total_Share_cost'] = pre_Total_Share_cost

    elif round(dic["Share"]) == 0:
        dic["new_SharePrise"] = 0

    dic["TotalValues"] = dic["TotalShareValues"] + dic["AvableCash"]
    # dic['tradePresend'] = str(tradePersent)

    dic["HoldingPresentage"] = round(dic["TotalShareValues"] / dic["TotalValues"], 3)

    if mode == "SELL" or mode == "BUY":
        dic["treade"] = tradePersent

    # print(PreClosePrice, df_d['close'], statsdic['TotalShareValues'])
    return dic, trade


def distion(df, range_day=123, col_List=["Avg"]):  # 文本筛选重建
    """
    决策布尔值创建器
    df = pd.DataFrame
    daylists=[5, 10, 21]
    """
    loop = 0

    col_L = ["date"]
    col_L.extend(col_List)
    _df = df.loc[:, col_L]
    tempL = []
    lists = []
    priceL = []

    if range_day > 30:
        ran_gap = int(range_day / 2)
    else:
        ran_gap = range_day
    for startday in range(df.shape[0] - range_day):
        n = startday + range_day
        loop_dic = df.iloc[startday:n][col_L].to_dict()

        for col in col_L:
            loop_dic[col] = list(loop_dic[col].values())

        feature_dic = {"date": loop_dic["date"][0]}

        for key in col_L[1:]:
            price = df.iloc[startday][key]
            templist = loop_dic[key]
            maxindex = templist.index(max(templist))
            minindex = templist.index(min(templist))

            key = str(range_day) + key + "_pre"
            if maxindex == 0:
                feature_key = 1
            elif minindex == 0:
                feature_key = -1
            else:
                feature_key = 0

            tempL.append(feature_key)
            priceL.append(price)

            for x in range(ran_gap):
                if len(tempL) > (x + 1):
                    if tempL[-(x + 2)] == feature_key:
                        if feature_key == 1:
                            if priceL[-(x + 2)] < price * 0.99:
                                lists[-(x + 1)][key] = 0
                            else:
                                feature_key = 0
                        elif feature_key == -1:
                            if priceL[-(x + 2)] < price * 0.99:
                                feature_key = 0
                            else:
                                lists[-(x + 1)][key] = 0
                else:
                    break
            feature_dic[key] = feature_key
            lists.append(feature_dic)

    _df = pd.DataFrame(lists)
    df = pd.merge(df, _df, on="date", how="left")

    print("** Marker {}_pre **".format(range_day).center(60, " "))

    return df
